class Slingshot {
  float x, y;
  Vec2 ZERO_POS;
  Vec2 FRONT_KNOT, BACK_KNOT;
  Vec2 releasePos;
  float MAX_LENGTH;
  Pig pig;
  boolean isReleased;
  PImage imgFront, imgBack, imgPocket;
  
  Slingshot(float x, float y) {
    this.x = x;
    this.y = y;
    this.ZERO_POS = new Vec2(this.x, this.y - 38);
    this.MAX_LENGTH = 60;
    this.FRONT_KNOT = new Vec2(this.x - 12, this.y - 38);
    this.BACK_KNOT = new Vec2(this.x + 14, this.y - 38);
    this.imgFront = loadImage("slingshot_front.png");
    this.imgBack = loadImage("slingshot_back.png");
    this.imgPocket = loadImage("slingshot_pocket.png");
  }
  
  void drawFront() {
    if (this.pig != null) {
      Vec2 pos = box2d.getBodyPixelCoord(pig.body);
      if (pos.sub(this.ZERO_POS).length() > 0) {
        if (isReleased) {
          if (this.releasePos.x < this.ZERO_POS.x && pos.x > this.ZERO_POS.x ||
              this.releasePos.x > this.ZERO_POS.x && pos.x < this.ZERO_POS.x ||
              this.releasePos.y < this.ZERO_POS.y && pos.y > this.ZERO_POS.y ||
              this.releasePos.y > this.ZERO_POS.y && pos.y < this.ZERO_POS.y ||
              this.releasePos.sub(this.ZERO_POS).length() == 0) {
              this.pig = null;
          }
        }
        if (this.pig != null) {
          pos.subLocal(this.ZERO_POS);
          float angle = atan2(pos.y, pos.x);
          float len = pos.normalize() + 16;
          pos.mulLocal(len);
          pos.addLocal(this.ZERO_POS);
          pushStyle();
          stroke(48, 22, 8);
          strokeWeight(2);
          line(this.FRONT_KNOT.x, this.FRONT_KNOT.y, pos.x, pos.y);
          popStyle();
          pushMatrix();
          translate(pos.x, pos.y);
          rotate(angle);
          image(this.imgPocket, 0, 0, 12, 15);
          popMatrix();
        }
      }
    }
    pushMatrix();
    translate(this.x, this.y);
    image(this.imgFront, 0, 0, 40, 120);
    popMatrix();
  }
  
  void drawBack() {
    pushMatrix();
    translate(this.x, this.y);
    image(this.imgBack, 0, 0, 40, 120);
    popMatrix();
    if (this.pig != null) {
      Vec2 pos = box2d.getBodyPixelCoord(pig.body);
      if (pos.sub(this.ZERO_POS).length() > 0) {
        if (isReleased) {
          if (this.releasePos.x < this.ZERO_POS.x && pos.x > this.ZERO_POS.x ||
              this.releasePos.x > this.ZERO_POS.x && pos.x < this.ZERO_POS.x ||
              this.releasePos.y < this.ZERO_POS.y && pos.y > this.ZERO_POS.y ||
              this.releasePos.y > this.ZERO_POS.y && pos.y < this.ZERO_POS.y ||
              this.releasePos.sub(this.ZERO_POS).length() == 0) {
              this.pig = null;
          }
        }
        if (this.pig != null) {
          pos.subLocal(this.ZERO_POS);
          float angle = atan2(pos.y, pos.x);
          float len = pos.normalize() + 12;
          pos.mulLocal(len);
          pos.addLocal(this.ZERO_POS);
          pushStyle();
          stroke(48, 22, 8);
          strokeWeight(2);
          line(this.BACK_KNOT.x, this.BACK_KNOT.y, pos.x, pos.y);
          popStyle();
          pushMatrix();
          translate(pos.x, pos.y);
          rotate(angle);
          image(this.imgPocket, 0, 0, 12, 15);
          popMatrix();
        }
      }
    }
  }
  
  void load(Pig p) {
    this.pig = p;
    this.isReleased = false;
  }
  
  // should this be force based rather than velocity based?
  void release() {
    if (this.pig == null) return;
    this.releasePos = box2d.getBodyPixelCoord(this.pig.body);
    Vec2 velocity = this.ZERO_POS.sub(this.releasePos);
    velocity.mulLocal(0.55);
    velocity.y = -velocity.y;
    pig.body.setLinearVelocity(velocity);
    this.isReleased = true;
  }
  
  Vec2 constrainPos(float x, float y) {
    Vec2 pos = new Vec2(x, y);
    Vec2 constrainedPos = pos.sub(this.ZERO_POS);
    if (constrainedPos.normalize() > this.MAX_LENGTH) {
      constrainedPos.mulLocal(this.MAX_LENGTH);
      constrainedPos.addLocal(this.ZERO_POS);
      pos = constrainedPos;
    }
    return pos;
  }
}
